Koncepte te tjera te POO

Enkapsulimi

Enkapsulimi ka te beje me menyren sesi ne e deklarojme vizibilitetin e variablave anetare dhe funksioneve anetare te nje klase. Kur ne krijojme nje klase duhet te pyesim vetveten se cilat prej anetareve te klases duhet te jene te aksesueshme nga jashte klases. P.sh. ne rast se kemi nje variabel anetare public $ngjyra te nje klase Makine, a eshte e lejueshme qe ketij variabli te jepet vlere nga jashte dmth. $makina1->ngjyra = "E Kuqa" ? Ne rast se dikush krijon nje objekt $makina2 a eshte e lejueshme te aksesoje vleren p.sh. echo $makina1->ngjyra; ?

Anetaret me akses public

Per te vendosur akseset tek variablat dhe funksionet anetare te nje klase perdoren modifikuesit e aksesit (ang. access modifiers) te cilet jane public, private dhe protected.

Ne rast se nuk specifikojme nje modifikues aksesi per nje anetar te klases, atehere si modifikues aksesi default vendoset public. Nese shihni ne shembujt e mesiperm nuk kemi vendosur modifikues aksesi per funksionet p.sh. kemi deklaruar function ul_shpejtesine($shpejtesia) {...} dhe jo public function ul_shpejtesine($shpejtesia) {...}. Ne kete rast eshte e njejta gje sepse kur nuk e specifikojme vendoset aksesi public.

Anetaret (variabla ose funksione te klases) me modifikues aksesi public mund te aksesohen ne tre situata te mundshme:

  • Brenda klases ku anetaret jane deklaruar
  • Jashte klases ku anetaret jane deklaruar
  • Brenda klases femije qe trashegon klasen ku anetaret jane deklaruar

Le te marrim nje shembull:

<?php

class Makine {

    public $ngjyra = "E Kuqe";
    public $shpejtesia = 120;

    public function ul_shpejtesine($shpejtesia) {
        $this->shpejtesia = $shpejtesia;
    }

    public function ndalo() {
        $this->ul_shpejtesine(80);

        $this->ul_shpejtesine(60);

        $this->ul_shpejtesine(30);

        $this->ul_shpejtesine(0);
    }
}

// Jashte klases:

$makina1 = new Makine();

$makina1->ngjyra = "E Zeze";

Ne shembullin e mesiperm duke qene se variabli anetare public $ngjyra eshte publik, ai mund te aksesohet edhe jashte klases si ne rastin e mesiperm $makina1->ngjyra = "E Zeze" ku kemi ndryshuar edhe ngjyren.

Funksioni ul_shpejtesine() perdoret per te ulur shpejtesine e makines sipas vleres qe i kalojme. Por ne te vertete duke qene se variabli anetar public $shpejtesia eshte publik ne mund ta ulim shpejtesine edhe pa perdorur funksionin e mesiperm thjesht duke ndryshuar variablin $makina1->$shpejtesia = 0;. Duke pare me kujdes veme re qe ne kete rast edhe funksioni ndalo() eshte i panevojshem pasi shpejtesia ulet ne zero thjesht duke aksesuar variablin anetare $makina1->$shpejtesia. Epo kjo nuk eshte gjeja e duhur pasi nuk duhet te lejohet qe shpejtesia te ulet ne menyre te menjehershme nga jashte klases.

Ajo qe na vjen ne ndihme eshte modifikuesi i aksesit private, me te cilin percaktojme se cilet prej anetareve te klases duhet te jene private, te paaksesueshme jashte klases ku jane deklaruar.

Anetaret me akses private

Anetaret (variabla ose funksione te klases) me modifikues aksesi private mund te aksesohen ne nje situate te mundshme:

  • Brenda klases ku anetaret jane deklaruar
  • Jashte klases ku anetaret jane deklaruar
  • Brenda klases femije qe trashegon klasen ku anetaret jane deklaruar

Ne menyre qe anetaret $shpejtesia dhe ul_shpejtesine() te mos aksesohen jashte klases le ti vendosim aksesin private:

<?php

class Makine {

    private $shpejtesia = 120;

    private function ul_shpejtesine($shpejtesia) {
        $this->shpejtesia = $shpejtesia;
    }

    public function ndalo() {
        $this->ul_shpejtesine(80);

        $this->ul_shpejtesine(60);

        $this->ul_shpejtesine(30);

        $this->ul_shpejtesine(0);
    }
}

// Jashte klases:

$makina1 = new Makine();

//Do te gjeneroje error:
$makina1->shpejtesia = 50;

Ne rastin e mesiperm deklarata $makina1->shpejtesia = 50 do te gjeneroje nje error, pasi nuk na lejohet te aksesojme variablin anetar ne kete menyre. E vetmja gje qe mund te bejme eshte te ndalojme, duke ulur shpejtesine ne menyre graduale, pra te therrasim funksionin $makina1->ndalo(), pasi vetem ky funksion eshte i aksesueshem nga jashte klases.

Ne rast se nje klase femije trashegon klasen e mesiperme Makine, klasa femije nuk do te kete akses ne funksionin anetar ul_shpejtesine() dhe ne variablin anetar $shpejtesia pasi ata jane te deklaruar private.

Shembull:

<?php

class Autoveture extends Makine {

    public $kilometrazhi = 80;

}


$autoveture = new Autoveture();

//Therret funksionin e trasheguar nga klasa prind
$autoveture->ndalo();

//Do te gjeneroje error:
$autoveture->ul_shpejtesine(30);

Edhe pse klasa Autoveture trashegon klasen Makine, ajo nuk mund te perdore anetaret private te klases prind, dhe deklarata $autoveture->ul_shpejtesine(30) do te gjeneroje gabim. Ne menyre qe kjo te jete e mundur na vijne ne ndihme modifikuesi i aksesit protected.

Anetaret me akses protected

Anetaret (variabla ose funksione te klases) me modifikues aksesi protected mund te aksesohen ne dy situata te mundshme:

  • Brenda klases ku anetaret jane deklaruar
  • Jashte klases ku anetaret jane deklaruar
  • Brenda klases femije qe trashegon klasen ku anetaret jane deklaruar

Pra, anetaret e deklaruar protected nuk jane te aksesueshem jashte klases ku jane deklaruar:

<?php

class Makine {

    private $shpejtesia = 120;

    protected function ul_shpejtesine($shpejtesia) {
        $this->shpejtesia = $shpejtesia;
    }

    public function ndalo() {
        $this->ul_shpejtesine(80);

        $this->ul_shpejtesine(60);

        $this->ul_shpejtesine(30);

        $this->ul_shpejtesine(0);
    }
}

// Jashte klases:

$makina1 = new Makine();

//Do te gjeneroje error pasi nuk mund te aksesohet jashte klases
$makina1->ul_shpejtesine(50);

Ne deklaraten $makina1->ul_shpejtesine(50) do te gjenerohet gabim sepse anetari ul_shpejtesine() nuk mund te aksesohet jashte klases. Por, ne ndryshim nga private, ne kete rast protected na lejon qe te perdorim anetaret brenda klasave femije, qe trashegojne klasen ku ata jane deklaruar.

Shembull:

<?php

class Autoveture extends Makine {
    public $kilometrazhi = 80;
}

$autoveture = new Autoveture();

//Nuk do te gjeneroje error
$autoveture->ul_shpejtesine(30);

Konstantet

Nje konstante klase eshte nje anetar i klases, pak a shume si nje variabel por eshte e pandryshueshme dhe emri i saj nuk fillon me simbolin $. Konstantet mund te shoqerohen me modifikuesit e aksesit, por ne rast se nuk i shoqerojme ato jane public si parazgjedhje (default).

Deklarimi i konstanteve:

<?php

class Punonjes {

    const MOSHA_MAKSIMALE = 65;

    function printo_moshen_maksimale() {
        print 65;
    }
}

Konstantet deklarohen me ane te termit const shoqeruar me emrin e tyre, dhe me pas me vleren. Lind pyetja se si i aksesojme konstantet brenda apo jashte klases.

Perdorimi i konstanteve jashte klases:

<?php

echo Punonjes::MOSHA_MAKSIMALE;

Jashte klases vleren e konstantes mund ta aksesojme duke perdorur emrin e klases shoqeruar me simbolin ::, dhe me pas emri i konstantes.

Perdorimi i konstanteve brenda klases:

<?php

class Punonjes {

    const MOSHA_MAKSIMALE = 65;

    function printo_moshen_maksimale() {

        //self - i referohet klases aktuale
        print self::MOSHA_MAKSIMALE;
    }
}

Brenda klases na vjen ne ndihme operatori self i cili i referohet klases aktuale ku jemi. Pra, pak a shume ne te njejten menyre sic referohen jashte klases por ne vend te emrit te klases perdoret termi self qe referon klasen aktuale.

Nuk mund te ndryshojme vleren e nje konstanteje pasi ajo eshte deklaruar. Deklarimi Punonjes::MOSHA_MAKSIMALE = 60; do te gjeneronte nje gabim.

Klasat abstrakte

Klasat abstrakte jane klasa te vecanta prej te cilave nuk mund te krijohen kurre objekte. Ato perdoren me se shumti si klasa prind (superklasa) per klasa te tjera qe i trashegojne. Pra, brenda nje klase abstrakte mund te implementojme nje liste funksionalitetesh, te cilat pasi klasa te trashegohet mund te perdoren nga klasat femije.

Ne shembujt e kaluar permendem nje klase prind Kafshe dhe dy klasa femije Zog dhe Qen. Ne te vertete ne nuk duhet te lejojme qe dikush te krijoje objekte te tipit Kafshe pasi eshte shume e paspecifikuar. Per kete arsye e deklarojme kete klase abstrakte.

Klasat abstrakte deklarohen me termin abstract perpara:

<?php

abstract clas Kafshe {

    public $ngjyra;
    public $madhesia;

    function merr_frym() {
        print ("Thith oksigjenin qe ndodhet ne ajer.");
    }
}

Duke deklaruar kete klase abstrakte, nuk na lejohet te krijojme objekte per kete klase, dhe deklarata $kafshe = new Kafshe(); do te na gjeneronte nje gabim.

Pervec klasave, mund te deklarojme edhe funksione abstrakte abstract function hello() {}. Ne rast se ne nje klase deklarojme nje funksion abstrakt, atehere edhe vete klasa duhet deklaruar abstrakte. Vetem klasat abstrakte mund te mbajne funksione abstrakte. Trupin e nje funksioni abstrakt mund ta leme bosh. Funksionet abstrakte krijohen per te detyruar klasat femije (qe trashegojne klasen ku eshte deklaruar) qe te implementojne funksionin ne fjale, te ndertojne trupin e ketij funksioni duke shkruajtur kod brenda tij. Ne rast te kundert do te gjenerohet nje error nga PHP-ja. Kur implementohet funksioni ne klasen femije modifikuesi i aksesit nuk duhet te ndryshoje, ai mbetet i njejte perndryshe do te gjenerohet gabim.

Shembull:

<?php

abstract clas Kafshe {

    public $ngjyra;
    public $madhesia;

    public function merr_frym() {
        print ("Thith oksigjenin qe ndodhet ne ajer.");
    }

    abstract public function pershendet() {};
}

Ne klasen femije qe trashegon klasen e mesiperme Kafshe, jemi te detyruar qe te implementojme funksionin pershendet().

<?php

abstract clas Qen extends Kafshe {

    //Hiqet termi abstract
    public function pershendet() {

        print ("Ham Ham");

    };
}

$qen = new Qen();

$qen->merr_frym();
$qen->pershendet();

Objekti $qen mund te perdore si anetaret e trasheguar nga klasa prind, ashtu edhe ato te implementuar brenda klases Qen.

Nderfaqet (Interfaces)

Nderfaqet deklarohen per te dhene nje liste me emra funksionesh per implementuesit e saj. Nderfaqet jane thjesht nje shabllon qe tregon nje liste me funksione te ndryshme pa trup pra pa kllapat { dhe }. Klasat qe implementojne kete nderfaqe jane te detyruara te implementojne te gjitha funksionet e listuara. Nje nderfaqe nuk mund te permbaje variabla anetare, por mund te permbaje konstante dhe funksione anetare. Cdo funksion qe krijohet ne nderfaqe duhet te deklarohe public dhe nuk mund te kete kod konkret ne brendesi te saj, pasi ata jane pa trup. Nderfaqet deklarohen me ane te termit interface.

Shembull:

<?php

interface ReceteGatimi
{
   public function perberesit(); 
}

Ne menyre qe te perdorim nje nderfaqe duhet te perdorim termin implements pas deklarimit te nje klase. Supozojme qe kemi nje klase me emrin Bakllava:

<?php

class Bakllava implements ReceteGatimi {

    //Jemi te detyruar te implementojme nje trup per kete funksion:

   public function perberesit() {

         print("Miell, Veze, Sheqer, Arra etj...");

   }; 
}

Ashtu si me klasat abstrakte (qe implementuam funksionet abstrakte), jemi te detyruar te implementojme te gjitha funksionet qe ndodhen ne nderfaqe. Nuk mund te krijojme nje objekt nga nje nderfaqe p.sh. deklarimi $recete = new ReceteGatimi() gjeneron gabim. SHohim qe nderfaqet sherbejne si nje shabllon qe te na informojne se cilat funksione duhet te deklarojme ne klasat qe e perdorin ate.

Ndryshimi ndermjet klasave abstrakte dhe nderfaqeve

Nderfaqet dhe klasat abstrakte jane pak a shume te njejta. Te dyja ndihmojne per krijimin e shablloneve per klasat qe kane nevoje per to. Me poshte listojme disa ndryshime ndermjet tyre:

  • Funksionet ne klasat abstrakte mund te deklarohen abstract ose funksione normale. Nqs. nje funksion deklarohet abstract, atehere funksioni duhet te implementohet ne klasen femije (qe trashegon klasen ne fjale). Tek nderfaqet te gjitha funksionet jane abstrakte, keshtuqe te gjitha duhet te implementohen ne klasen qe implementon nderfaqen ne fjale.

  • Na lejohet te deklarojme nje funksion public, private ose protected ne klasat abstrakte. Ne nderfaqe te gjitha funksionet duhet te jene public.

  • Ne klasat abstrakte na lejohet te krijojme variabla anetare dhe funksione me kod konkret brenda tyre per sa kohe qe nuk jane deklaruar abstrakte. Nje nderfaqe nuk ka variabla anetare, dhe funksionet nuk mund te kene nje trup.

  • Nje klase mund te trashegoje 1 klase abstrakte, por nje klase mund te implementoje nje numer te pafundem nderfaqesh edhe pse nderfaqet nuk kane lidhje me njera-tjetren.

Nje klase mund te implementoje nje numer te pafundem nderfaqesh duke i ndare ato me presje:

<?php

class Bakllava implements ReceteGatimi, GatimTradicional { ... }

Nje klase mund te trashegoje nje klase prind, dhe te implementoje disa nderfaqe ne te njejten kohe:

<?php

class Bakllava extends Embelsire implements ReceteGatimi, GatimTradicional { ... }

Type Hinting

Deri me tani kemi mesuar disa tipe te dhenash sic jane integer, stringa, array etj, po ashtu shpjeguam objektet si nje tip kompleks. Ne shume raste do te na duhet te dime dhe te jemi te sigurte per tipin e variables qe presim qe te na kaloje si argument ne nje metode specifike te nje klase, ose ne nje funksion te pavarur. Kjo gje perfshin ate cfare quhet 'Type Hinting'.

Shembull:

<?php

function feste(array $pjesmarresit) {

    // le te filloje festa...
}

$pjesmarres = array("Alban", "Xhenty", "Erjon", "Brilant");

feste($pjesmarres);

Ne shembullin e mesiperm funksioni feste(...) pranon vetem nje argument te tipit array, dhe kjo eshte specifikuar duke vendosur perpara emrit te parametrit termin array, pra array $pjesmarresit. Ne rast se ne provojme te kalojme ne kete funksion nje numer feste(10); ose nje string feste("Alban, Xhenty, Erjon, Brilant") apo cfaredo lloj tipi tjeter qe nuk eshte array atehere do te gjenerohet nje error nga PHP-ja.

'Type Hinting' perdoret edhe per objektet. Supozojme qe kemi nje klase Student dhe nje klase Kurs:

<?php

class Student {

    public $emri;
    public $mosha;

    function __construct($emri) {
        $this->emri = $emri;
    }
}

class Kurs {

    public $emri;

    function __construct($emri) {
        $this->emri = $emri;
    }
}

Ndertojme nje funksion te pavarur i cili regjistron studentet ne nje kurs te caktuar. Duhet te kemi kujdes, pasi argumentet qe duhet te pranoje ky funksion nuk duhet te jene te cfaredoshem, por detyrimisht nje student dhe nje kurs.

<?php

function regjistro(Student $student, Kurs $kurs) {

    echo "Studenti " . $student->emri . " u regjistrua ne kursin " . $kurs->emri;

}

Kemi perdorur type hinting per te siguruar qe tipi i argumenteve qe do te kalohen do te jete i duhuri. Student $student detyron qe argumenti i pare te jete i tipit Student, dhe Kurs $kurs detyron qe argumenti i dyte te jete i tipit Kurs. Ne rast se nuk ndiqet ky rregull atehere do te gjenerohet gabim.

Polimorfizmi

Supozojme qe kemi nje klase Molle, Dardhe dhe Portokall. Ato jane te ndryshme nga njera-tjetra por qendrojne ne te njejten kategori si fruta. Keshtuqe do te ishte e duhur krijimi i nje nderfaqeje te quajtur Frut, dhe implementimi i kesaj nderfaqeje nga tre klasat Molle, Dardhe dhe Portokall. Ky quhet polimorfizem. Nje grumbull klasash me strukture dhe funksionalitet te ndryshem, por qe te gjitha perdorin te njejten nderfaqe.

Supozojme qe kemi nje nderfaqe te quajtur Llafazan:

<?php

interface Llafazan {
    public function flet_shume();
}

Krijojme dhe dy klasa qe implementojne kete nderfaqe:

<?php

//Klasa Kafshe eshte klasa e perdorur ne shembujt e kaluar

class Qen extends Kafshe implements Llafazan {

    public function flet_shume() {
        print "Ham, Ham!";
    }
}


class Mace extends Kafshe implements Llafazan {

    public function flet_shume() {
        print "Miau, Miau!";
    }
}

Supozojme qe kemi nje funksion te pavarur (jo pjese te ndonje klase) qe pranon nje objekt te tipit Llafazan, dmth. nje objekt te nje klase qe implementon nderfaqen Llafazan.

<?php

function testoTeFoluren(Llafazan $llafazan) {
    $llafazan->flet_shume();
}

Kemi perdorur 'Type Hinting' duke detyruar qe objekti qe do te kalojme ne funksion te jete i tipit Llafazan. Pavaresisht se cfare lloj objekti do te kalojme ne funksionin testoTeFoluren(), mjafton te jete i nje klase qe implementon nderfaqen Llafazan dhe ai do te therrase funksionin ->flet_shume() te ketij objekti.

<?php

$qen = new Qen();

testoTeFoluren($qen);    //Rezultati: Ham, Ham!

$mace = new Mace();

testoTeFoluren($mace);    //Rezultati: Miau, Miau!

Duke futur objekte te ndryshme si input marrim edhe rezultate te ndryshme. Kjo eshte fuqia e polimorfizmit ne POO.

Variablat dhe metodat statike

Variabel apo metode statike konsiderohen ato variabla ose metoda te cilat mund te aksesohen pa nevojen e krijimit te nje objekti. Ne shpjegimet e meparshme qartesuam qe kur krijojme nje objekt te ri, te gjithe anetaret e klases kopjohen ne nje bllok te ri memorie. Objektet kane kopjet e tyre te vecanta, dhe nuk i ngaterrojne me njeri-tjetrin. Ne rast se anetaret jo-statik jane te vecante per cdo objekt, variablat dhe metodat statike nuk kopjohen per cdo objekt te ri qe krijohet. Ato gjenden aty edhe pa krijuar asnje objekt. Edhe ne rast se krijohen disa objekte ato jane aty te vetme. Le te marrim nje shembull me klasen Student:

<?php

class Student {

    public $emri;
    public $mosha;

    public $numri_studenteve = 0;

    function __construct($emri) {
        $this->emri = $emri;

        $numri_studenteve++;
    }
}

Variabli $numri_studenteve do te mbaje numrin e studenteve te krijuar. Ne momentin qe krijohet nje objek i ri, do te therritet funksioni __construct. Fillimisht do te ruaje emrin e studentit $this->emri = $emri;, dhe me pas duke qene se po krijojme nje student te ri do te inkrementoje variablin $numri_studenteve++.

<?php

$st1 = new Student("Alban Afmeti");

echo $st1->numri_studenteve;    //Rezultati: 1

$st2 = new Student("Gentjan Afmeti");

echo $st2->numri_studenteve;    //Rezultati: 1

$st3 = new Student("Brilant Afmeti");

echo $st3->numri_studenteve;    //Rezultati: 1

Shohim qe pavaresisht se vazhdojme krijojme objekte te reja variabli $numri_studenteve mban vleren 1. Arsyeja pse ndodh kjo eshte se secili prej objekteve te mesiperme ka nje kopje te vecante te variablit $numri_studenteve, keshtuqe nga 0 qe eshte fillimisht, ky variabel merr vleren 1 pasi krijohet objekti. Ne momentin e krijimit te objekteve te tjera, nuk eshte i njejti variabel qe inkrementohet, por eshte nje kopje tjeter e ketij variabli ne objektin tjeter.

Per kete arsye lind nevoja qe objektet te kene dicka te perbashket. Ketu vijne ne ndihme anetaret statik te klases. Transformojme klasen e mesiperme me variabel statik:

<?php

class Student {

    public $emri;
    public $mosha;

    public static $numri_studenteve = 0;

    function __construct($emri) {
        $this->emri = $emri;

        $numri_studenteve++;
    }
}

Variablat ose metodat statike aksesohen ashtu si konstantet qe trajtuam me lart. Jashte klases aksesohen duke shkruajtur emrin e klases, shoqeruar me operatorin ::, dhe me pas emri i variablit ose metodes, Student::$numri_studenteve. Brenda klases vjen ne ndihme operatori self, pra self::$numri_studenteve

<?php

$st1 = new Student("Alban Afmeti");

echo Student::$numri_studenteve;    //Rezultati: 1

$st2 = new Student("Gentjan Afmeti");

echo Student::$numri_studenteve;    //Rezultati: 2

$st3 = new Student("Brilant Afmeti");

echo Student::$numri_studenteve;    //Rezultati: 3

Ne kete rast shohim qe ne variablin statik ruhet me te vertete numri i studenteve te krijuar. Ne te njejten menyre perdoren edhe metodat statike:

<?php

class Student {

    public $emri;
    public $mosha;

    private static $numri_studenteve = 0;

    function __construct($emri) {
        $this->emri = $emri;

        $numri_studenteve++;
    }

    public static function getNumriStudenteve() {
        return self::$numri_studenteve;
    }
}

Kemi kthyer variablin statik $numri_studenteve me akses privat dhe kemi ndertuar metoden statike getNumriStudenteve() e cila thjeshte na kthen varialin $numri_studenteve.

<?php

$st1 = new Student("Alban Afmeti");
$st2 = new Student("Gentjan Afmeti");
$st3 = new Student("Brilant Afmeti");

echo Student::getNumriStudenteve();    //Rezultati: 3

Variablat dhe metodat statike mund te perdoren edhe nqs. nuk kemi krijuar asnje objekt. Pasi ato nuk jane pjese e drejperdrejte e objektit por jane pjese e klases.

<?php

//Therrasim metoden statike pa krijuar asnje objekt:

echo Student::getNumriStudenteve();    //Rezultati: 0

Duhet te kemi kujdes pasi variabli special $this qe mban referencen e objektit aktual nuk mund te perdoret brenda metodave statike. Arsyeja eshte e qarte pasi dukeqenese metodat statike nuk jane pjese e objektit, referenca $this e objektit aktual eshte i palogjikshem. Metodat statike mund te therriten edhe pa krijuar asnje objekt, keshtuqe nuk ka sens qe te perdoret variabli $this brenda tyre duke referuar objektin aktual.

<?php

class Student {

    private $emri = "Alban Afmeti";

    public getEmri() {
        return $this->emri;
    }
}

$student = new Student();
$student->getEmri();

Perdorimi i $this ne funksionin getEmri ka sens sepse ne momentin qe therritet metoda $student->getEmri(), nje objekt eshte krijuar $student i cili po therret kete metode, keshtuqe $this ne ate moment te kohes mban te njejten reference si $student. Dukeqenese metodat statike nuk therriten nepermjet objekteve, por nepermjet klases atehere $this nuk eshte se po i referohet ndonje objekti te krijuar, keshtuqe do te jepte gabim. Kjo eshte arsyeja pse nuk perdorim $this brenda metodave statike, pasi do te gjeneronte nje gabim.

Nga ana tjeter, ne mund te perdorim variablat apo metodat statike brenda metodave jo-statike, si ne rastin e meposhtem:

<?php

class Student {

    private $emri = "Alban Afmeti";
    public static $kursi = "Programim ne web";

    public printo() {
        print ("Emri: " . $this->emri . "    Kursi: " . self::$kursi);
    }
}

$student = new Student();
$student->getEmri();

Kjo nuk do te shkaktonte ndonje problem, pasi anetaret statik jane gjithmone aty te disponueshem per t'i perdorur.

Metodat magjike

PHP-ja na ofron disa metoda magjike te cilat ekzekutohen automatikisht kur nje ngjarje e caktuar ndodh. Funksioni i konstruktorit, te cilin e trajtuam me lart, konsiderohet gjithashtu metode magjike, pasi edhe ai ekzekutohet kur nje ngjarje e caktuar ndodh. Funksioni __construct ekzekutohet kur krijohet nje objekt i ri. Emri i metodave magjike ne PHP fillon me dy viza poshte __, per arsye qe te dallohen nga metodat normale. Le te ndertojme nje klase ku te kemi deklaruar edhe disa metoda magjike:

<?php

class Student {

    private $emri = "Alban Afmeti";
    public static $kursi = "Programim ne web";

    public printo() {
        print ("Emri: " . $this->emri . "    Kursi: " . self::$kursi);
    }

    public function __get( $name )
    {
       echo "Variabli $name nuk ekziston!";
    }

    public function __set( $name, $value )
    {
       echo "Vlera $value nuk mund te vendoset sepse variabli $name nuk ekziston!";
    }

    public function __call( $name, $params )
    {
       echo "Metoda $name nuk ekziston! <br>";
       print_r( $params );
    }

    public function __toString()
    {
       return 'Emri i objektit eshte ' . $this->emri;
    }

    public function __clone()
    {
       echo 'Ju klonuat objektin ' . $this->emri;
    }

    public function __invoke()
    {
       echo 'Nuk mund ta therrisni kete objekt si funksion!';
    }

    public function __destruct()
    {
       echo 'Objekti u shkaterrua!';
    }
}
  • __get - Therritet kur ne perpiqemi te aksesojme nje variabel qe nuk ekziston ne klase. Funksioni pranon 1 parameter qe mban emrin e variablit qe ne u perpoqem te aksesojme.
<?php

$student = new Student();

echo $student->mosha;

Dukeqenese objekti i tipit Student nuk permban ndonje variabel me emrin mosha, do te therritet automatikisht metoda __get e klases Student, dhe si rezultat do te printohet: Variabli mosha nuk ekziston!

  • __set - Therritet kur ne perpiqemi t'i japim vlere nje variabli qe nuk ekziston ne klase. Funksioni pranon 2 parametra, i pari mban emrin e variablit dhe i dyti mban vleren qe u perpoqem qe t'i japim.
<?php

$student = new Student();

$student->mosha = 25;

Dukeqenese objekti i tipit Student nuk permban ndonje variabel me emrin mosha, do te therritet automatikisht metoda __set e klases Student, dhe si rezultat do te printohet: Vlera 25 nuk mund te vendoset sepse variabli mosha nuk ekziston!

  • __call - Therritet kur ne perpiqemi te aksesojme nje metode qe nuk ekziston ne klase. Funksioni pranon 2 parametra, ku i pari mban emrin e metodes qe ne u perpoqem te aksesojme, ndersa i dyti eshte nje array qe mban argumentet qe kaluam ne kete metode.
<?php

$student = new Student();

echo $student->getLendet("Fizike", "Informatike");

Dukeqenese objekti i tipit Student nuk permban ndonje metode me emrin getLendet, do te therritet automatikisht metoda __call e klases Student, dhe si rezultat do te printohet:

Metoda getLendet nuk ekziston!
Array ( [0] => Fizike [1] => Informatike)
  • __toString - Therritet kur ne perpiqemi te printojme nje objekt te kesaj klase. Ne rast se deklarojme nje metode te tille ne klase ne duhet te kthejme nje string dhe asgje tjeter.
<?php

$student = new Student();

echo $student;

Dukeqenese objekti $student po kalohet drejperdrejt si argument i metodes echo, do te therritet automatikisht metoda __toString e klases Student, dhe si rezultat do te printohet: Emri i objektit eshte Alban Afmeti

  • __clone - Therritet kur ne perpiqemi te klonojme nje objekt. Per te klonuar nje objekt perdoret termi clone. Kur klonojme nje objekt ne po krijojme nje objekt te ri me te njejtat variabla dhe metoda si objekti i klonuar. Gjate klonimit ruhen gjithashtu edhe vlerat e variablave, duke na dhene mundesine te ruajme nje kopje te objektit ne nje gjendje te caktuar.
<?php

$student = new Student();

$student2 = clone $student;

Dukeqenese po realizohet nje klonim i objektit $student, do te therritet automatikisht metoda __clone e klases Student, dhe si rezultat do te printohet: Ju klonuat objektin Alban Afmeti

  • __invoke - Therritet kur ne perpiqemi te ekzekutojme nje objekt ashtu si nje funksion, duke i shtuar pas emrit te objektit kllapat ().
<?php

$student = new Student();

$student();

Ne kete rast do te therritet automatikisht metoda __invoke e klases Student, dhe si rezultat do te printohet: Nuk mund ta therrisni kete objekt si funksion!

  • __destruct - Therritet kur nje objekt shkaterrohet. Objektet shkaterrohen automatikisht kur skripti PHP perfundon. Nese duam te shkaterrojme nje objekt me heret mund te perdorim funksionin e pavarur unset(...)
<?php

$student = new Student();

unset($student);

Ne kete rast do te therritet automatikisht metoda __destruct e klases Student, dhe si rezultat do te printohet: Objekti u shkaterrua!

Vargezimi i metodave

Vargezimi i metodave ka te beje me therritjen e metodave njera pas tjetres. Supozojme qe kemi nje klase Njeri me 3 metoda ne te:

<?php

class Njeri {

    private $shpejtesia = 0;  // km/ore

    public function ecen() {
        $this->shpejtesia = 5;
    }

    public function vrapon() {
        $this->shpejtesia = 15;
    }

    public function ndalon() {
        $this->shpejtesia = 0;
    }
}

Per te therritur keto metoda, na duhet te krijojme nje variabel qe mban reference tek nje objekt:

<?php

$njeriu = new Njeri();

Me pas me ane te ketij variabli (qe mban referencen e nje objekti ne memorie) mund te therrasim metodat me ndihmen e operatorit ->:

<?php

$njeriu->ecen();

$njeriu->vrapon();

$njeriu->ndalon();

Sic e shohim per te therritur keto 3 metoda na jane dashur 3 rreshta kodi. Per te therritur nje metode te nje klase, mjafton te kemi nje reference tek objekti i klases dhe me ane te operatorit -> mund te therrasim cfaredo lloj metode jo-statike publike te klases. Ne duam te gjejme nje menyre qe t'i therrasim metodat e mesiperme ne forme vargu:

<?php
$njeriu->ecen()->vrapon()->ndalon();

Shohim qe metoden vrapon() e kemi therritur pas metodes ecen(). Te njejten gje kemi bere me metoden ndalon() ku e kemi therritur pas metodes vrapon(). Por, me lart thame qe per te therritur nje metode te nje klase duhet qe operatori -> te vije pas nje reference te nje objekti te kesaj klase. Pra, qe metoda vrapon() te therritet ne menyren e mesiperme duhet qe shprehja $njeriu->ecen() te jete nje reference tek nje objekt, ose me sakte te ktheje nje objekt. Aktualisht nuk kthen asgje, ndaj per te zgjidhur kete problem ndryshojme permbajtjen e metodes ecen():

<?php

    public function ecen() {
        $this->shpejtesia = 5;

        //Kthen objektin aktual
        return $this;

    }

Mjafton qe te shtojme shprehjen return $this;, pasi me ane te saj, metoda do te ktheje nje reference te objektit aktual. Ne kete rast, shprehja $njeriu->ecen() do te ktheje nje reference te objektit aktual. Por, objekti aktual eshte $njeriu. Pra, shprehja $njeriu->ecen() kthen nje reference te objektit $njeriu. Epo atehere zgjidhja u arrit. Meqenese shprehja $njeriu->ecen() kthen objektin $njeriu, atehere jemi te lire te therrasim nje metode tjeter ne vazhdim te kesaj shprehje, keshtuqe therrasim metoden vrapon(). Ky quhet vargezim i metodave. Per te bere te mundur vargezimin tek te gjitha metodat ndryshojme permbajtjen edhe tek metodat e tjera.

<?php

class Njeri {

    private $shpejtesia = 0;  // km/ore

    public function ecen() {
        $this->shpejtesia = 5;
        return $this;
    }

    public function vrapon() {
        $this->shpejtesia = 15;
        return $this;
    }

    public function ndalon() {
        $this->shpejtesia = 0;
        return $this;
    }
}

Ne kete moment jemi te lire te perdorim vargezimin:

<?php

$njeriu = new Njeri();

$njeriu->ecen()->vrapon()->ndalon();

results matching ""

    No results matching ""